package vsy.buzzwordbingo.sort;

import java.lang.reflect.InvocationTargetException;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Map;

import vsy.buzzwordbingo.sort.OrderedComparator.Order;

@SuppressWarnings("rawtypes")
public class ComparatorProvider {
	private Map<Class, Map<String, Map<String, Comparator>>> comparators;
	private HashMap<Class, String> defaultSorts;
	private HashMap<Class, Map<String, String>> defaultOrders;

	private String descending;
	private String ascending;

	@SuppressWarnings("unchecked")
	public <T> Comparator<T> getComparator(Class<T> c, String sort, String order) {
		Map<String, Map<String, Comparator>> compsForClass = comparators.get(c);
		if (compsForClass == null)
			return null;

		Map<String, Comparator> compsForClassAndSort = compsForClass.get(sort);
		if (compsForClassAndSort == null) {
			sort = defaultSorts.get(c);
			if (sort == null)
				return null;
			compsForClassAndSort = compsForClass.get(sort);
			if (compsForClassAndSort == null)
				return null;
		}

		Comparator comparator = compsForClassAndSort.get(order);
		if (comparator == null) {
			Map<String, String> defaultOrdersForClass = defaultOrders.get(c);
			if (defaultOrdersForClass == null)
				return null;
			order = defaultOrdersForClass.get(sort);
			if (order == null)
				return null;
			comparator = compsForClassAndSort.get(order);
		}

		return comparator;
	}

	public void setAscending(String asc) {
		this.ascending = asc;
	}

	public void setDescending(String desc) {
		this.descending = desc;
	}

	public void setComparators(Map<String, Map<String, String>> comparatorDefs)
			throws ClassNotFoundException, IllegalArgumentException,
			SecurityException, InstantiationException, IllegalAccessException,
			InvocationTargetException, NoSuchMethodException {
		comparators = new HashMap<Class, Map<String, Map<String, Comparator>>>();
		for (String className : comparatorDefs.keySet()) {
			Class<?> c = Class.forName(className);
			Map<String, String> comparatorDefsForClass = comparatorDefs
					.get(className);
			Map<String, Map<String, Comparator>> comparatorsForClass = new HashMap<String, Map<String, Comparator>>();
			for (String attribute : comparatorDefsForClass.keySet()) {
				String compClassName = comparatorDefsForClass.get(attribute);
				Class<?> comparatorClass = Class.forName(compClassName);
				Map<String, Comparator> comps = new HashMap<String, Comparator>();
				Comparator ascComparator = (Comparator) comparatorClass
						.getConstructor(Order.class).newInstance(
								Order.ASCENDING);
				Comparator descComparator = (Comparator) comparatorClass
						.getConstructor(Order.class).newInstance(
								Order.DESCENDING);
				comps.put(ascending, ascComparator);
				comps.put(descending, descComparator);
				comparatorsForClass.put(attribute, comps);
			}
			comparators.put(c, comparatorsForClass);
		}
	}

	public void setDefaultSorts(Map<String, String> defaultSortDefs)
			throws ClassNotFoundException {
		defaultSorts = new HashMap<Class, String>();
		for (String className : defaultSortDefs.keySet()) {
			Class<?> c = Class.forName(className);
			defaultSorts.put(c, defaultSortDefs.get(className));
		}
	}

	public void setDefaultOrders(
			Map<String, Map<String, String>> defaultOrderDefs)
			throws ClassNotFoundException {
		defaultOrders = new HashMap<Class, Map<String, String>>();
		for (String className : defaultOrderDefs.keySet()) {
			Class<?> c = Class.forName(className);
			Map<String, String> defaultOrdersDefsForClass = defaultOrderDefs
					.get(className);
			defaultOrders.put(c, defaultOrdersDefsForClass);
		}
	}
}
